package com.jack.payment.util.common;


import com.jack.payment.constant.SettingRuleConstant;
import com.jack.payment.constant.enums.TimeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * 时间工具类
 */
@Component
public class TimeUtil {
    private Logger log = LoggerFactory.getLogger(TimeUtil.class);
    // 年-月-日 小时:分钟:秒   获取日期格式精确到秒
    private static SimpleDateFormat currentData = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    // 年-月-日-小时-分钟-秒
    private static final SimpleDateFormat specialData = new SimpleDateFormat("yyyy-MM-dd-HH:mm:ss");
    // 年-月-日
    private static SimpleDateFormat formatData = new SimpleDateFormat("yyyy-MM-dd");
    // 年 月 日
    private static SimpleDateFormat dataFormatter = new SimpleDateFormat("yyMMdd");
    // 年 月
    private static SimpleDateFormat monthFormatter = new SimpleDateFormat("yyMM");
    // 年
    private static SimpleDateFormat yearFormatter = new SimpleDateFormat("yyyy");
    // 仅两字符年
    private static SimpleDateFormat twoYearFormatter = new SimpleDateFormat("yy");
    // 年月日时分秒, 无任何符号
    private static SimpleDateFormat SIMPLE_FORMATTER = new SimpleDateFormat("yyyyMMddHHmmss");

    // 格式数组
    private final static SimpleDateFormat[] formats = new SimpleDateFormat[]{
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
            new SimpleDateFormat("yyyy-MM-dd HH:mm"),
            new SimpleDateFormat("yyyy-MM-dd HH"),
            new SimpleDateFormat("yyyy-MM-dd"),
            new SimpleDateFormat("yyyy-MM"),
            new SimpleDateFormat("yyyy")
    };

    /** 根据不同格式返回不同日期格式 (不带-的) **/
    public static String getCurrentData(Date date,TimeEnum timeEnum) {
        String currentStr = new String();
        switch (timeEnum) {
            case DAY:
                // yyMMdd
                currentStr = dataFormatter.format(date);
                break;
            case MONTH:
                // yyMM
                currentStr = monthFormatter.format(date);
                break;
            case YEAR:
                // yyyy
                currentStr = yearFormatter.format(date);
                break;
            default:
                currentStr = dataFormatter.format(date);
                break;
        }
        return currentStr;
    }

    /** 获取现在时间 yyyy-MM-dd HH:mm:ss **/
    public static String getCurrentData() {
        Date date = new Date();
        return currentData.format(date);
    }

    /**
     *  年月日时分秒, 无任何符号
     * @return
     */
    public static String getSimpleCurrentData() {
        Date date = new Date();
        return SIMPLE_FORMATTER.format(date);
    }

    /**
     * 特殊字符描述, 如图片路径
     */
    public static String getSpecialData() {
        Date date = new Date();
        return specialData.format(date);
    }

    public static String getCurrentData(TimeEnum timeEnum) {
        Date date = new Date();
        return getCurrentData(date, timeEnum);
    }



    /** 获取当前时间戳 **/
    public static long getCurrentTime() {
        return System.currentTimeMillis() / 1000;
    }


    /** 这个时间段的 月份有多少天 **/
    public static Integer currenTimeDay(Long timestamp) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }
    /** 获取本月有多少天 **/
    public static Integer currenTimeDay() {
        return currenTimeDay(System.currentTimeMillis());
    }

    /** 两个时间戳 相差多少天 [不满一天 按 一天算] **/
    public static Integer timeDiscrepancy(Long startTimeStamp, Long endTimeStamp, Integer sumDay) {
        if (startTimeStamp.longValue() >= endTimeStamp.longValue()) {
            return sumDay;
        }
        Instant instant1 = Instant.ofEpochMilli(startTimeStamp);
        Instant instant2 = Instant.ofEpochMilli(endTimeStamp);
        Duration duration = Duration.between(instant1, instant2);
        long day = duration.toDays();
        return (int) day + 1;
    }
    /** 两个时间戳 相差多少天 [不满一天 按 一天算] **/
    public static Integer timeDiscrepancy(Long startTimeStamp, Long endTimeStamp) {
        Instant instant1 = Instant.ofEpochMilli(startTimeStamp * 1000);
        Instant instant2 = Instant.ofEpochMilli(endTimeStamp * 1000);
        Duration duration = Duration.between(instant1, instant2);
        long day = duration.toDays();
        if (day < 0) {
            return 0;
        }
        return (int) day + 1;
    }



    /**
     * 格式日期转成 时间戳
     * @param dateString
     * @return
     */
    public static Long timeConversion(String dateString) {
        Long currentTime = getCurrentTime();
        // 尝试使用不同的格式解析日期字符串
        for (SimpleDateFormat format : formats) {
            format.setLenient(false);               // 设置为不宽松模式，严格遵循格式
            try {
                Date date = format.parse(dateString);
                Long analysis = date.getTime() / 1000;      // 成功解析，返回时间戳（秒为单位）
                if (analysis > currentTime) {
                    // 解析时间不能大于现在时间
                    return currentTime;
                }
                return analysis;
            } catch (ParseException e) {
                // 解析失败，继续尝试下一个格式
            }
        }
        // 所有格式都尝试过了，还是无法解析
        return currentTime;
    }


    /** 根据TimeEnum 计算返回多少秒的 **/
    public static long getTimeEnumSecode(Integer num, TimeEnum timeEnum) {
        long compute = 0;
        switch (timeEnum) {
            case WEEK:
                // 计算出(num) 周 以后的时间搓
                compute = 60 * 60 * 24 * 7 * num;
                break;
            case DAY:
                // 计算出(num) 天 以后的时间搓
                compute = 60 * 60 * 24 * num;
                break;
            case HOUR:
                // 计算出(num) 小时 以后的时间搓
                compute = 60 * 60 * num;
                break;
            case MINUTE:
                // 计算出(num) 分钟 以后的时间搓
                compute = 60 * num;
                break;
            case SECOND:
                // 计算出(num) 秒 以后的 时间搓
                compute = num;
                break;
        }
        return compute;
    }

    /** 根据选择的日期类型, 返回现在计算号的时间戳 **/
    private static long getChooseTimeStamp(Integer num, Long timestamp, TimeEnum timeEnum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp);
        switch (timeEnum) {
            case YEAR:
                // 计算出(num) 年 以后的时间搓
                calendar.add(Calendar.YEAR, num);
                break;
            case QUARTER:
                // 计算出(num) 年季度 以后的时间搓
                calendar.add(Calendar.MONTH, 3 * num);
                break;
            case MONTH:
                // 计算出(num) 月 以后的时间搓
                calendar.add(Calendar.MONTH, num);
                break;
            case WEEK:
                // 计算出(num) 周 以后的时间搓
                calendar.add(Calendar.WEDNESDAY, num);
                break;
            case DAY:
                // 计算出(num) 天 以后的时间搓
                calendar.add(Calendar.DATE, num);
                break;
            case HOUR:
                // 计算出(num) 小时 以后的时间搓
                calendar.add(Calendar.HOUR, num);
                break;
            case MINUTE:
                // 计算出(num) 分钟 以后的时间搓
                calendar.add(Calendar.MINUTE, num);
                break;
            case SECOND:
                // 计算出(num) 秒 以后的 时间搓
                calendar.add(Calendar.SECOND, num);
                break;
        }
        return calendar.getTimeInMillis();
    }
    /** 根据现在时间毫秒 进行增加 **/
    public static long getCurrentTimeStamp(Integer num, TimeEnum timeEnum) {
        return getChooseTimeStamp(num, System.currentTimeMillis(), timeEnum);
    }
    /** 根据现在时间获取秒 **/
    public static long getCurrentSecode(Integer num, TimeEnum timeEnum) {
        return getCurrentTimeStamp(num, timeEnum) / 1000;
    }
    /** 传入的date, 进行时间加减 **/
    public static long getCurrentTimeStamp(Integer num, Date date, TimeEnum timeEnum) {
        return getChooseTimeStamp(num, date.getTime(), timeEnum);
    }


    /** 根据具体时间 毫秒性 **/
    public static long getCurrentTimeStamp(Integer num, Long timstamp, TimeEnum timeEnum) {
        return getChooseTimeStamp(num, timstamp * 1000, timeEnum);
    }
    /** 根据现在时间获取秒 **/
    public static long getCurrentSecode(Integer num, Long timstamp, TimeEnum timeEnum) {
        return getCurrentTimeStamp(num, timstamp, timeEnum) / 1000;
    }
    /** 获取时间戳 **/
    public static long getTimeEnumTimeStamp(Integer num, TimeEnum timeEnum) {
        return getTimeEnumSecode(num, timeEnum) * 1000;
    }

    public static String resultDate() {
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_YEAR, 1);
        date = calendar.getTime();
        return getCurrentData(date, TimeEnum.DAY);
    }

    public static Long timeTransition(String timeStr) {
        DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(timeStr, formatter);
        Instant instant = zonedDateTime.toInstant();
        return instant.toEpochMilli() / 1000;
    }


    /**
     * 时间段拼接, 如: api 格式如下: api_D_23_12_28 (M:月, W: 周 D: 天 Y 年 Q: 季)
     */
    public static String timeFormatJoin(String joinStr, Long currentTime, TimeEnum timeEnum) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(currentTime * 1000);
        joinStr += "_";
        switch (timeEnum) {
            case YEAR:
                joinStr = joinStr + timeEnum.getTimeType() + "_" + twoYearFormatter.format(calendar.getTime());
                break;
            case QUARTER:
                joinStr =
                        joinStr + timeEnum.getTimeType() + "_" + twoYearFormatter.format(calendar.getTime()) +
                "_" + ((calendar.get(Calendar.MONTH) + 1) / 3)
                ;
                break;
            case MONTH:
                joinStr =
                        joinStr + timeEnum.getTimeType() + "_" + monthFormatter.format(calendar.getTime());
                break;
            case WEEK:
                joinStr =
                        joinStr + timeEnum.getTimeType() + "_" + monthFormatter.format(calendar.getTime()) +
                                "_" + (calendar.get(Calendar.WEEK_OF_MONTH));
                break;
            case DAY:
            default:
                joinStr =
                        joinStr + timeEnum.getTimeType() + "_" + dataFormatter.format(calendar.getTime());
                break;

        }
        return joinStr;
    }
}
